;;;;;;;;;;;;;;;;;;;;  c-family plugins  ;;;;;;;;;;;;;;;;;;;;
(require 'c-eldoc)
(require 'xcscope)
(require 'smart-compile)
(require 'doxymacs)
(require 'flymake)
(require 'ctypes)
(require 'cmake-mode)
(require 'google-c-style)

;;;;;;;;;;;;;;;;;;;;  hook  ;;;;;;;;;;;;;;;;;;;;
(add-hook 'c-mode-common-hook '(lambda ()
                                 (progn
                                   (outline-minor-mode)
                                   (my-c-mode-auto-pair)
                                   (c-turn-on-eldoc-mode)
                                   (doxymacs-mode)
                                   (gtags-mode)
                                   (require 'doc-mode)
                                   (doc-mode)
                                   ;;(company-mode)
                                   (setq tab-width 4 indent-tabs-mode nil)
                                   (c-toggle-auto-hungry-state 1)
                                   ;; (flyspell-prog-mode)
                                   (make-local-variable 'pre-command-hook)
                                   (add-hook 'pre-command-hook 'cancel-auto-new-line)
                                   (local-set-key (kbd "C-<tab>") 'company-clang)
                                   (local-set-key (kbd "C-z c s") 'company-clang-set-prefix)
                                   (local-set-key "\;" 'insert-semicolon)
                                   (local-set-key [return] 'c-context-line-break)
                                   (local-set-key "\C-m" 'end-of-newline)
                                   (local-set-key [return] 'c-context-line-break)
                                   (subword-mode 1)
                                   (c-toggle-auto-hungry-state 1)
                                   (c-toggle-auto-newline 1)
                                   )))
(add-hook 'c-mode-common-hook 'google-set-c-style)

(add-hook 'c-mode-hook  '(lambda () (progn
                                      'c-mode-common-hook)))

(add-hook 'c++-mode-hook  '(lambda () (progn
                                        'c-mode-common-hook)))

;;;;;;;;;;;;;;;;;;;;  basic setting  ;;;;;;;;;;;;;;;;;;;;
(autoload 'gtags-mode "gtags" "" t)
(c-initialize-cc-mode t)
(c-set-offset 'inline-open 0)
(c-set-offset 'friend '-)
(c-set-offset 'substatement-open 0)
(setq comment-style 'extra-line)
(setq c-macro-shrink-window-flag t)
(setq c-macro-preprocessor "cpp")
(setq c-macro-cppflags " ")
(setq c-macro-prompt-flag t)
(setq c-eldoc-includes "`pkg-config gtk+-2.0 --cflags` -I./ -I../ ")
(setq ctypes-write-types-at-exit t)
(setq gdb-many-windows t)
(setq flymake-start-syntax-check-on-newline nil)
(setq c-echo-syntactic-information-p t)
(setq c-report-syntactic-errors t)


;;;;;;;;;;;;;;;;;;;;  paren-related and auto completion  ;;;;;;;;;;;;;;;;;;;;
(setq pushovers
      '(
        (?\" . (lambda () (forward-char 1) ))
        (?\' . (lambda () (forward-char 1) ))
        (?\) . (lambda () (up-list 1) ))
        (?\] . (lambda () (up-list 1) ))
        (?\} . (lambda () (up-list 1) ))
        ))

(setq defaults
      '(
        (?\" . (lambda () (skeleton-pair-insert-maybe nil) ))
        (?\' . (lambda () (skeleton-pair-insert-maybe nil) ))
        (?\) . (lambda () (insert-char ?\) 1) ))
        (?\] . (lambda () (insert-char ?\] 1) ))
        (?\} . (lambda () (insert-char ?\} 1) ))
        ))
(defun indent-or-complete ()
  (interactive)  
  (defun do-yas-expand ()  
    (let ((yas/fallback-behavior 'return-nil))
      (yas/expand)))
  
  (if (minibufferp)
      (minibuffer-complete)
    (if (or (not yas/minor-mode)
            (null (do-yas-expand)))
        (if (looking-at "\\>")
            (hippie-expand nil)
          (indent-for-tab-command)))))


(defun move-over (char)
  (if (eq (char-after) char)
      (funcall (cdr (assoc char pushovers)))
    (funcall (cdr (assoc char defaults)))
    )
  )
(defun move-over-bracket ()  (interactive)(move-over ?\) ))
(defun move-over-curly ()  (interactive)(move-over ?\} ))
(defun move-over-square ()  (interactive)(move-over ?\] ))
(defun move-over-quote ()  (interactive)(move-over ?\' ))
(defun move-over-dbl-quote ()  (interactive)(move-over ?\" ))
(defun my-c-mode-auto-pair ()
  (interactive)
  (setq skeleton-pair t)
  (local-set-key (kbd "(") 'skeleton-pair-insert-maybe)
  (local-set-key (kbd "[") 'skeleton-pair-insert-maybe)
  ;;  (local-set-key (kbd "{") 'skeleton-c-mode-left-brace)
  (local-set-key (kbd "{") 'skeleton-pair-insert-maybe)
  (local-set-key (kbd "'") 'skeleton-pair-insert-maybe)
  (local-set-key (kbd "\"") 'skeleton-pair-insert-maybe)
  (local-set-key (kbd ")") 'move-over-bracket)
  (local-set-key (kbd "]") 'move-over-square)
  (local-set-key (kbd "}") 'move-over-curly)
  (local-set-key (kbd "'") 'move-over-quote)
  (local-set-key (kbd "\"") 'move-over-dbl-quote)
  )

(setq hippie-expand-try-functions-list
      '(
        ;;company-clang
        ;; senator-try-expand-semantic
        try-expand-dabbrev
        try-expand-dabbrev-visible
        try-expand-dabbrev-all-buffers
        try-expand-dabbrev-from-kill
        try-expand-list
        try-expand-list-all-buffers
        try-expand-line
        try-expand-line-all-buffers
        try-complete-file-name-partially
        try-complete-file-name
        try-expand-whole-kill
        ;;        ispell-complete-word
        )
      )

(defun my-doxymacs-font-lock-hook ()
  (if (or (eq major-mode 'c-mode) (eq major-mode 'c++-mode))
      (doxymacs-font-lock)))

(defun skeleton-c-mode-left-brace (arg)
  (interactive "*P")
  (if  (c-in-literal (c-most-enclosing-brace (c-parse-state)))
      (self-insert-command 1)
    ;; auto insert complex things.
    (let* ((current-line (delete-and-extract-region (line-beginning-position) (line-end-position)))
           (lines (and arg (mark t) (delete-and-extract-region (mark t) (point))))
           (after-point (make-marker)))
      (setq lines (and lines
                       (with-temp-buffer
                         (insert lines)
                         (goto-char (point-min))
                         (delete-blank-lines)
                         (delete-blank-lines)
                         (goto-char (point-max))
                         (delete-blank-lines)
                         (delete-blank-lines)
                         (buffer-string))))
      (save-excursion
        (let* ((old-point (point)))
          (insert (if current-line current-line "")  "{\n")
          (and lines (insert lines))
          (move-marker after-point (point))
          (insert "\n}\n")
          (indent-region old-point (point) nil)))
      (goto-char after-point)
      (c-indent-line)
      )))


;;;;;;;;;;;;;;;;;;;; make & compile setting ;;;;;;;;;;;;;;;;;;;;
(autoload 'mode-compile "mode-compile"  "Command to compile current buffer file based on the major mode" t)
(autoload 'mode-compile-kill "mode-compile"  "Command to kill a compilation launched by `mode-compile'" t)
(autoload 'cmake-mode "cmake-mode" "Major mode for editing CMake files." t)
(add-to-list 'auto-mode-alist '("CMakeLists\\.txt\\'" . cmake-mode))
(add-to-list 'auto-mode-alist '("\\.cmake\\'" . cmake-mode))

;;;;;;;;;;;;;;;;;;;;  cflow setting  ;;;;;;;;;;;;;;;;;;;;
;;http://emacser.com/emacs-cflow.htm
(require 'cflow-mode)
(defvar cmd nil nil)
(defvar cflow-buf nil nil)
(defvar cflow-buf-name nil nil)
 
(defun yyc/cflow-function (function-name)
  "Get call graph of inputed function. "
  (interactive "sFunction name:\n")
  ;; (interactive (list (car (senator-jump-interactive "Function name: "
  ;;                                                   nil nil nil))))
  (setq cmd (format "cflow  -b --main=%s %s" function-name buffer-file-name))
  (setq cflow-buf-name (format "**cflow-%s:%s**"
                               (file-name-nondirectory buffer-file-name)
                               function-name))
  (setq cflow-buf (get-buffer-create cflow-buf-name))
  (set-buffer cflow-buf)
  (setq buffer-read-only nil)
  (erase-buffer)
  (insert (shell-command-to-string cmd))
  (pop-to-buffer cflow-buf)
  (goto-char (point-min))
  (cflow-mode)
  )

;;;;;;;;;;;;;;;;;;;;  gtk doc  ;;;;;;;;;;;;;;;;;;;;
(autoload 'gtk-doc-insert "gtk-doc"
  "Add a documentation header to the current function." t)
(autoload 'gtk-doc-insert-section "gtk-doc"
  "Add a section documentation header at the current position." t)

;;;;;;;;;;;;;;;;;;;;  junk  ;;;;;;;;;;;;;;;;;;;;
;; (ctypes-read-file nil nil t t)
;; (ctypes-auto-parse-mode 1)
;; (defun my-indent-or-complete ()
;;   (interactive)
;;   (if (looking-at "\\>")
;;       (hippie-expand nil)
;;     (indent-for-tab-command))
;;   )
